package rule

import (
	"errors"
	"fmt"
	"go-iot/app/models"
	"go-iot/app/common/mysql"
	"gorm.io/gorm"
	"time"
)

const maxDeviceIdsLength = 100

// 分页查询
func PageRule(page *models.PageQuery, createId *int64) (*models.PageResult[models.Rule], error) {
	var rules []models.Rule
	var total int64
	
	query := mysql.DB.Model(&models.Rule{})
	
	// 添加条件过滤
	for _, condition := range page.Condition {
		query = query.Where(condition)
	}
	
	// 添加创建者过滤
	if createId != nil {
		query = query.Where("create_id = ?", *createId)
	}
	
	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, err
	}
	
	// 执行分页查询
	if err := query.Select("id", "name", "state", "desc", "create_id", "create_time").
		Order("create_time desc, id desc").
		Offset(page.PageOffset()).
		Limit(page.PageSize).
		Find(&rules).Error; err != nil {
		return nil, err
	}
	
	result := models.PageUtil(total, page.PageNum, page.PageSize, rules)
	return &result, nil
}

func AddRule(ob *models.RuleModel) error {
	if len(ob.Name) == 0 {
		return errors.New("name must be present")
	}
	
	rs, err := GetRule(ob.Id)
	if err != nil {
		return err
	}
	if rs != nil {
		return errors.New("规则已经存在")
	}
	
	if len(ob.DeviceIds) > maxDeviceIdsLength {
		return fmt.Errorf("设备数不能超过%v", maxDeviceIdsLength)
	}
	
	ob.State = models.Stopped
	en := ob.ToEnitty()
	en.CreateTime = time.Now()
	
	// 使用事务处理
	return mysql.DB.Transaction(func(tx *gorm.DB) error {
		// 插入规则
		if err := tx.Create(&en).Error; err != nil {
			return err
		}
		
		// 插入规则与设备的关联
		if len(ob.DeviceIds) > 0 {
			var relDevices []models.RuleRelDevice
			for _, deviceId := range ob.DeviceIds {
				relDevices = append(relDevices, models.RuleRelDevice{
					RuleId:   en.Id,
					DeviceId: deviceId,
				})
			}
			
			if err := tx.CreateInBatches(relDevices, 10).Error; err != nil {
				return err
			}
		}
		
		return nil
	})
}

func UpdateRule(ob *models.RuleModel) error {
	if len(ob.DeviceIds) > maxDeviceIdsLength {
		return fmt.Errorf("设备数不能超过%v", maxDeviceIdsLength)
	}
	
	en := ob.ToEnitty()
	
	// 构建更新字段
	updates := map[string]interface{}{}
	if len(ob.Name) > 0 {
		updates["name"] = en.Name
	}
	if len(ob.TriggerType) > 0 {
		updates["trigger_type"] = en.TriggerType
	}
	if len(ob.ProductId) > 0 {
		updates["product_id"] = en.ProductId
	}
	if len(en.Trigger) > 0 {
		updates["trigger"] = en.Trigger
	}
	if len(ob.Actions) > 0 {
		updates["actions"] = en.Actions
	}
	if len(ob.Type) > 0 {
		updates["type"] = en.Type
	}
	if len(ob.Cron) > 0 {
		updates["cron"] = en.Cron
	}
	if len(ob.Desc) > 0 {
		updates["desc"] = en.Desc
	}
	
	if len(updates) == 0 {
		return errors.New("no data to update")
	}
	
	// 使用事务处理
	return mysql.DB.Transaction(func(tx *gorm.DB) error {
		// 更新规则
		if err := tx.Model(&models.Rule{Id: en.Id}).Updates(updates).Error; err != nil {
			return err
		}
		
		// 删除旧的关联
		if err := tx.Where("rule_id = ?", en.Id).Delete(&models.RuleRelDevice{}).Error; err != nil {
			return err
		}
		
		// 添加新的关联
		if len(ob.DeviceIds) > 0 {
			var relDevices []models.RuleRelDevice
			for _, deviceId := range ob.DeviceIds {
				relDevices = append(relDevices, models.RuleRelDevice{
					RuleId:   en.Id,
					DeviceId: deviceId,
				})
			}
			
			if err := tx.CreateInBatches(relDevices, 10).Error; err != nil {
				return err
			}
		}
		
		return nil
	})
}

// 更新在线状态
func UpdateRuleStatus(state string, id int64) error {
	if id == 0 {
		return errors.New("id must be present")
	}
	if len(state) == 0 {
		return errors.New("state must be present")
	}
	
	return mysql.DB.Model(&models.Rule{Id: id}).Update("state", state).Error
}

func DeleteRule(ob *models.Rule) error {
	return mysql.DB.Delete(ob).Error
}

func GetRule(sceneId int64) (*models.RuleModel, error) {
	if sceneId == 0 {
		return nil, nil
	}
	
	// 查询规则基本信息
	var rule models.Rule
	result := mysql.DB.Where("id = ?", sceneId).First(&rule)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, result.Error
	}
	
	// 转换为模型
	m := models.RuleModel{}
	m.FromEnitty(rule)
	
	// 查询关联的设备ID
	var relDevices []models.RuleRelDevice
	if err := mysql.DB.Where("rule_id = ?", sceneId).Find(&relDevices).Error; err != nil {
		return nil, err
	}
	
	// 提取设备ID
	for _, rel := range relDevices {
		m.DeviceIds = append(m.DeviceIds, rel.DeviceId)
	}
	
	return &m, nil
}

func GetRuleMust(id int64) (*models.RuleModel, error) {
	p, err := GetRule(id)
	if err != nil {
		return nil, err
	}
	if p == nil {
		return nil, errors.New("rule not exist")
	}
	return p, nil
}

// AllRule 获取所有规则，可选择按状态过滤
func AllRule(state ...string) ([]models.Rule, error) {
	var rules []models.Rule
	query := mysql.DB
	
	// 如果提供了状态参数，则添加状态过滤
	if len(state) > 0 && state[0] != "" {
		query = query.Where("state = ?", state[0])
	}
	
	if err := query.Find(&rules).Error; err != nil {
		return nil, err
	}
	
	return rules, nil
}

